<?php
class Curl{
    //CURL handle
    private $handle = null;
    private $info = array();
    //CURL SETOPT info
    private $setopt = array(
        'port'=>10000,
        // USERAGENT,such as:"Mozilla/4.0"
        'userAgent'=>'',
        'timeOut'=>60,
        'useCookie'=>false,
        'ssl'=>false,
        'gzip'=>true,

        'proxy'=>false,
        'proxyType'=>'HTTP',
        //proxy host address, if use http, url shoul be:"http://www.proxy.com"
        //if use SOCKS5 url should be:"192.168.1.1"
        'proxyHost'=>'http://www.proxy.com',
        'proxyPort'=>1234,
        'proxyAuth'=>false,
        'proxyAuthType'=>'BASIC',
        'proxyAuthUser'=>'user',
        'proxyAuthPwd'=>'password',
    );

    public function __construct($setopt=array())
    {


        $this->setopt = array_merge($this->setopt,(array)$setopt);
        function_exists('curl_init') || die('CURL Library Not Loaded');
        $this->handle = curl_init();
        curl_setopt($this->handle, CURLOPT_PORT, $this->setopt['port']);
        if($this->setopt['proxy'])
        {
            $proxyType = $this->setopt['proxyType']=='HTTP' ? CURLPROXY_HTTP : CURLPROXY_SOCKS5;
            curl_setopt($this->handle, CURLOPT_PROXYTYPE, $proxyType);
            curl_setopt($this->handle, CURLOPT_PROXY, $this->setopt['proxyHost']);
            curl_setopt($this->handle, CURLOPT_PROXYPORT, $this->setopt['proxyPort']);
            if($this->setopt['proxyAuth'])
            {
                $proxyAuthType = $this->setopt['proxyAuthType']=='BASIC' ? CURLAUTH_BASIC : CURLAUTH_NTLM;
                curl_setopt($this->handle, CURLOPT_PROXYAUTH, $proxyAuthType);
                $user = "[{$this->setopt['proxyAuthUser']}]:[{$this->setopt['proxyAuthPwd']}]";
                curl_setopt($this->handle, CURLOPT_PROXYUSERPWD, $user);
            }
        }
        curl_setopt($this->handle, CURLOPT_FOLLOWLOCATION, true);
        if($this->setopt['ssl'])
        {
            curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, true);
        }

        $header = array('Accept: application/json','Content-Type: application/json');
        curl_setopt($this->handle, CURLOPT_HTTPHEADER, $header);
        $userAgent = $this->setopt['userAgent'] ? $this->setopt['userAgent'] : $_SERVER['HTTP_USER_AGENT'];
        curl_setopt($this->handle, CURLOPT_USERAGENT, $userAgent);
        curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, $this->setopt['timeOut']);
        curl_setopt($this->handle, CURLOPT_TIMEOUT, $this->setopt['timeOut']);
        if($this->setopt['gzip'])
        {
            curl_setopt($this->handle, CURLOPT_ENCODING, 'gzip');
        }
        if($this->setopt['useCookie'])
        {
            $cookfile = tempnam(sys_get_temp_dir(),'cuk');
            curl_setopt($this->handle, CURLOPT_COOKIEJAR, $cookfile);
            curl_setopt($this->handle, CURLOPT_COOKIEFILE, $cookfile);
        }
        curl_setopt($this->handle, CURLOPT_HEADER, true);
        curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, true) ;
        curl_setopt($this->handle, CURLOPT_BINARYTRANSFER, true) ;
    }

    public function get($url,$params=array(), $referer='', $auth = '')
    {
        return $this->_request('GET', $url, $params, array(), $referer, $auth);
    }

    /**
     * @param string $url
     * @param array $params: format: array('id'=>10,'name'=>'yuanwei')
     * @param array $uploadFile :
     * singlefile:array('img1'=>'./file/a.jpg')
     * multi-file:array('img'=>array('./file/a.jpg','./file/b.jpg'))
     * @param array $referer :
     */
    public function post($url,$params=array(),$uploadFile=array(), $referer='', $auth = '')
    {
//        print_r($params);
//        exit;
        return $this->_request('POST', $url, $params, $uploadFile, $referer, $auth);
    }

    public function patch($url,$params=array(),$uploadFile=array(), $referer='', $auth = '', $etag = '')
    {
    	//        print_r($params);
    	//        exit;
    	return $this->_request('PATCH', $url, $params, $uploadFile, $referer, $auth, $etag);
    }
    

    public function error()
    {
        return curl_error($this->handle);
    }

    public function errno()
    {
        return curl_errno($this->handle);
    }


    public function getInfo()
    {
        return $this->info;
    }


    public function __destruct()
    {
        curl_close($this->handle);
    }

    private function _request($method, $url, $params=array(), $uploadFile=array(), $referer='', $auth = '', $etag = '')
    {
        if($method == 'GET')
        {
            $url = $this->_parseUrl($url,$params);
            if($auth){
            	$header = array('Accept: application/json','Content-Type: application/json', 'Authorization: Basic '. $auth);
            	curl_setopt($this->handle, CURLOPT_HTTPHEADER, $header);
            }
        }

        curl_setopt($this->handle, CURLOPT_URL, $url);
        if($method == 'POST')
        {
            curl_setopt($this->handle, CURLOPT_POST, true);
            $postData = json_encode($params);
//            print_r($postData);
            //$postData = $this->_parsmEncode($params,false);
            if($uploadFile)
            {
                foreach($uploadFile as $key=>$file)
                {
                    if(is_array($file))
                    {
                        $n = 0;
                        foreach($file as $f)
                        {
                            $postData[$key.'['.$n++.']'] = '@'.realpath($f);
                        }
                    }else
                    {
                        $postData[$key] = '@'.realpath($file);
                    }
                }
            }
            curl_setopt($this->handle, CURLOPT_POSTFIELDS, $postData);
            curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, "POST");
            if ($auth){
                $header= array('Accept: application/json','Content-Type: application/json','Content-Length: ' . strlen($postData), 'Authorization: Basic '. $auth);
            }
            else{
            	$header= array('Accept: application/json','Content-Type: application/json','Content-Length: ' . strlen($postData));
            }
            
            curl_setopt($this->handle, CURLOPT_HTTPHEADER, $header);
        }

        //patch is not support yet.
        if($method == 'PATCH')
        {
        	curl_setopt($this->handle, CURLOPT_POST, true);
        	$postData = json_encode($params);
        	//            print_r($postData);
        	//$postData = $this->_parsmEncode($params,false);
        	if($uploadFile)
        	{
        		foreach($uploadFile as $key=>$file)
        		{
        			if(is_array($file))
        			{
        				$n = 0;
        				foreach($file as $f)
        				{
        					$postData[$key.'['.$n++.']'] = '@'.realpath($f);
        				}
        			}else
        			{
        				$postData[$key] = '@'.realpath($file);
        			}
        		}
        	}
        	curl_setopt($this->handle, CURLOPT_POSTFIELDS, $postData);
        	curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, "PATCH");
        	if ($auth){
        		$header= array('Accept: application/json','Content-Type: application/json','Content-Length: ' . strlen($postData), 'Authorization: Basic '. $auth);
        	}
        	else{
        		$header= array('Accept: application/json','Content-Type: application/json','Content-Length: ' . strlen($postData));
        	}
        
        	if($etag){
        		$header['If-Match'] = $etag;
        	}
        
        	curl_setopt($this->handle, CURLOPT_HTTPHEADER, $header);
        }
        
        if($referer)
        {
            curl_setopt($this->handle, CURLOPT_REFERER, $referer);
        }else
        {
            curl_setopt($this->handle, CURLOPT_AUTOREFERER, true);
        }
        $this->info['before'] = curl_getinfo($this->handle);
        $result = curl_exec($this->handle);
        $headerSize = curl_getinfo($this->handle, CURLINFO_HEADER_SIZE);
        $this->info['header'] = substr($result, 0, $headerSize);
        $result = substr($result, $headerSize);
        $this->info['after'] = curl_getinfo($this->handle);
        if($this->errno() == 0)
        { //&& $this->info['after']['http_code'] == 200
            return $result;
        }else
        {
            return false;
        }
    }

    private function _parseUrl($url,$params)
    {
        $fieldStr = $this->_parsmEncode($params);
        if($fieldStr)
        {
            $url .= strstr($url,'?')===false ? '?' : '&';
            $url .= $fieldStr;
        }
        return $url;
    }

    private function _parsmEncode($params,$isRetStr=true)
    {
        $fieldStr = '';
        $spr = '';
        $result = array();
        foreach($params as $key=>$value)
        {
            $value = urlencode($value);
            $fieldStr .= $spr.$key .'='. $value;
            $spr = '&';
            $result[$key] = $value;
        }
        return $isRetStr ? $fieldStr : $result;
    }
}
?>
